package org.jeecg.modules.login.api;

import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.Limit;
import org.jeecg.common.login.LoginService;
import org.jeecg.common.login.parameter.DoubleFactorAuthParameter;
import org.jeecg.common.login.parameter.DoubleFactorExecuteParameter;
import org.jeecg.common.login.parameter.OriginalParameter;
import org.jeecg.common.message.MessageItem;
import org.jeecg.common.message.UnicomSmsUtil;
import org.jeecg.modules.login.handler.ding.DingHandler;
import org.jeecg.modules.login.handler.mail.MailHandler;
import org.jeecg.modules.login.handler.wechat.WeChatEnterpriseHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Collections;
import java.util.UUID;

/**
 * 双因子登录
 *
 * @author jiangtianyi
 * @version 1.2.2
 */
@Slf4j
@RestController
@RequestMapping("/sys/double")
@ConditionalOnExpression("'${basicplatform.login.double-factor.enable:false}'.equals('true')")
public class DoubleFactorLogin {

    @Value("${basicplatform.login.double-factor.type:sms}")
    private String type;

    private final DingHandler dingHandler;

    private final WeChatEnterpriseHandler weChatEnterpriseHandler;

    private final MailHandler mailHandler;

    private final UnicomSmsUtil unicomSmsUtil;

    private final LoginService loginService;

    @PostMapping("/login")
    public Result<?> login(@RequestBody @Valid OriginalParameter originalParameter) {
        Result<?> result = loginService.getDoubleFactorParameter(originalParameter);
        if (result.isSuccess()) {
            DoubleFactorExecuteParameter doubleFactorExecuteParameter = (DoubleFactorExecuteParameter) result.getResult();
            if (Type.SMS.getName().equals(type)) {
                MessageItem messageItem = MessageItem.builder().customerMessageId(UUID.randomUUID().toString())
                        .messageTo(doubleFactorExecuteParameter.getMobile()).messageContent(doubleFactorExecuteParameter.getContent()).build();
                // 发送短信
                if (!unicomSmsUtil.sendSms(Collections.singletonList(messageItem))) {
                    result = Result.error("验证码发送失败！");
                }
            } else if (Type.DING.getName().equals(type)) {
                try {
                    String dingId = dingHandler.dingIdByPhone(doubleFactorExecuteParameter.getMobile());
                    dingHandler.send(dingId, doubleFactorExecuteParameter.getContent());
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    result = Result.error("验证码发送失败！");
                }
            } else if (Type.MAIL.getName().equals(type)) {
                try {
                    MailHandler.EntryBuilder entryBuilder = MailHandler.EntryBuilder.builder()
                            .subject("登录验证").to(doubleFactorExecuteParameter.getMail()).text(doubleFactorExecuteParameter.getContent()).build();
                    mailHandler.send(entryBuilder);
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    result = Result.error("验证码发送失败！");
                }
            } else if (Type.WE_CHAT.getName().equals(type)) {
                try {
                    String weChatId = weChatEnterpriseHandler.weChatIdByPhone(doubleFactorExecuteParameter.getMobile());
                    weChatEnterpriseHandler.send(weChatId, doubleFactorExecuteParameter.getContent());
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    result = Result.error("验证码发送失败！");
                }
            } else {
                result = Result.error("验证码发送类型未定义");
            }

            if (result.isSuccess()) {
                return loginService.writeCaptcha4DoubleFactor(doubleFactorExecuteParameter.getKey(), doubleFactorExecuteParameter.getCaptcha(), doubleFactorExecuteParameter.getSignature());
            }
        }
        return result;
    }

    /**
     * 接口限制：5 次/分钟 {@link Limit}
     * 验证短信验证码
     *
     * @param doubleFactorAuthParameter {@link DoubleFactorAuthParameter}
     * @author jiangtianyi
     * @since 1.0
     */
    @Limit(value = 5)
    @PostMapping("/reLogin")
    public Result<?> reLogin(@RequestBody @Valid DoubleFactorAuthParameter doubleFactorAuthParameter) {
        return loginService.auth4DoubleFactorParameter(doubleFactorAuthParameter);
    }

    public DoubleFactorLogin(DingHandler dingHandler, WeChatEnterpriseHandler weChatEnterpriseHandler, MailHandler mailHandler, UnicomSmsUtil unicomSmsUtil, LoginService loginService) {
        this.dingHandler = dingHandler;
        this.weChatEnterpriseHandler = weChatEnterpriseHandler;
        this.mailHandler = mailHandler;
        this.unicomSmsUtil = unicomSmsUtil;
        this.loginService = loginService;
    }

    private enum Type {
        /**
         * 短信
         */
        SMS("sms"),
        /**
         * 钉钉
         */
        DING("ding"),
        /**
         * 企业微信
         */
        WE_CHAT("we_chat"),
        /**
         * 邮件
         */
        MAIL("mail");

        final String name;

        public String getName() {
            return name;
        }

        Type(String name) {
            this.name = name;
        }
    }
}
